package com.wan.net.rpc.registry;

import cn.hutool.core.util.ObjectUtil;
import com.sun.istack.internal.NotNull;
import com.wan.net.config.HostAndPort;
import com.wan.net.core.client.Client;
import com.wan.net.rpc.invoker.client.RpcClient;
import com.wan.net.rpc.service.RpcService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 注册中心
 * @author wwh
 * @date 2022/6/20 20:33
 */
public interface Registry {
    Registry LOCAL = new LocalRegistry();

    /**
     * 注册
     * @param rpcService 服务
     */
    void registry(RpcService rpcService);

    /**
     * 取消注册（下线）
     * @param rpcService 服务
     */
    void unregister(RpcService rpcService);

    /**
     * 根据接口获取服务
     * @return 可能有多个
     */
    @NotNull List<RpcService> find(Class<?> serviceInterface);
    /**
     * 查找服务
     */
    default List<RpcService> find(RpcService rpcService){
        List<RpcService> rpcServices = find(rpcService.getServiceInterface());
        return rpcServices.stream().filter(service->{
            //地址对应
            HostAndPort hostAndPort = rpcService.getHostAndPort();
            if(hostAndPort != null && !hostAndPort.equals(service.getHostAndPort())){
                return false;
            }
            //参数对应
            Map<String, Object> params = rpcService.getParams();
            if(params != null && !params.isEmpty()){
                Map<String, Object> serviceParam = service.getParams();
                for (Map.Entry<String, Object> entry : params.entrySet()) {
                    Object value = serviceParam.get(entry.getKey());
                    if(value == null || ObjectUtil.notEqual(entry.getValue(),value)) {
                        return false;
                    }
                }
            }
            return true;
        }).collect(Collectors.toList());
    }

    class LocalRegistry implements Registry{
        private static final Logger logger = LoggerFactory.getLogger(LocalRegistry.class);

        protected final Map<Class<?>,List<RpcService>> serviceMap = new ConcurrentHashMap<>();

        @Override
        public void registry(RpcService rpcService) {
            serviceMap.computeIfAbsent(rpcService.getServiceInterface(),l->new ArrayList<>()).add(rpcService);
            logger.info("[rpc]新增服务节点{}",rpcService);
            //创建对应客户端
            Client client = Client.get(rpcService.getHostAndPort());
            if(client == null){
                new RpcClient(rpcService.getHostAndPort());
            }
        }

        @Override
        public void unregister(RpcService rpcService) {
            List<RpcService> rpcServices = serviceMap.get(rpcService.getServiceInterface());
            if(rpcServices != null && rpcServices.size() > 0){
                rpcServices.remove(rpcService);
                logger.info("[rpc]删除服务节点{}",rpcService);
            }
            //关闭对应的客户端
            Client client = Client.get(rpcService.getHostAndPort());
            if(client != null){
                client.close();
            }
        }

        @Override
        public List<RpcService> find(Class<?> serviceInterface) {
            return serviceMap.getOrDefault(serviceInterface,Collections.emptyList());
        }
    }

}
